package com.raulraja.view.aop;

import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * Aspect that Intercepts exceptions thrown resuting from a call initiate at the view layer
 */
@Aspect
public class ExceptionInterceptor {

	private final static Logger logger = Logger.getLogger(ExceptionInterceptor.class);

	/**
	 * Intercepts view manager method calls
	 */
	@Pointcut("execution(public * com.raulraja.view.manager.ViewManager+.*(..))")
	public void viewMethodPointcut(){
	}

	/**
	 * Provides around advice to view managers method calls by catching any exception an turning them into ExceptionVO objects that can be handled by the view
	 * @param pjp the proceeding join point
	 * @return the object resulting for the operation
	 */
	@Around("viewMethodPointcut()")
	public Object applyAroundAdvice(ProceedingJoinPoint pjp) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
		Object returnValue;
		try {
			returnValue = pjp.proceed();
		}
        catch (Throwable e) {
			logger.error(e.getLocalizedMessage());
			Class<?> returningClass = ((MethodSignature)pjp.getSignature()).getReturnType();
			Constructor<?> exceptionConstructor = returningClass.getConstructor(Throwable.class);
			returnValue = exceptionConstructor.newInstance(e);
		}

    	return returnValue;
    }
}
